home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / ofs / ofsDisk.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  27KB  |  844 lines

  1. /* 
  2.  * ofsDisk.c --
  3.  *
  4.  *    Routines related to managing local disks under the orginial sprite
  5.  *    file system. 
  6.  *
  7.  * Copyright 1987 Regents of the University of California
  8.  * All rights reserved.
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/ofs/ofsDisk.c,v 9.15 92/03/19 17:34:40 jhh Exp $ SPRITE (Berkeley)";
  20. #endif not lint
  21.  
  22.  
  23. #include <sprite.h>
  24.  
  25. #include <fs.h>
  26. #include <fsutil.h>
  27. #include <fsdm.h>
  28. #include <fslcl.h>
  29. #include <fsNameOps.h>
  30. #include <fsio.h>
  31. #include <fsprefix.h>
  32. #include <fsconsist.h>
  33. #include <devDiskLabel.h>
  34. #include <dev.h>
  35. #include <devFsOpTable.h>
  36. #include <sync.h>
  37. #include <rpc.h>
  38. #include <fsioDevice.h>
  39. #include <ofs.h>
  40.  
  41. #include <stdio.h>
  42.  
  43. static Fsdm_DomainOps ofsDomainOps = {
  44.     Ofs_AttachDisk,
  45.     Ofs_DetachDisk,
  46.     Ofs_DomainWriteBack,
  47.     Ofs_RereadSummaryInfo,
  48.     Ofs_DomainInfo,
  49.     Ofs_BlockAllocate,
  50.     Ofs_GetNewFileNumber,
  51.     Ofs_FreeFileNumber,
  52.     Ofs_FileDescInit,
  53.     Ofs_FileDescFetch,
  54.     Ofs_FileDescStore,
  55.     Ofs_FileBlockRead,
  56.     Ofs_FileBlockWrite,
  57.     Ofs_FileTrunc,
  58.     Ofs_DirOpStart,
  59.     Ofs_DirOpEnd
  60. };
  61.  
  62.  
  63. static Fscache_BackendRoutines  ofsBackendRoutines = {
  64.         Fsdm_BlockAllocate,
  65.         Fsdm_FileTrunc,
  66.         Fsdm_FileBlockRead,
  67.         Fsdm_FileBlockWrite,
  68.         Ofs_ReallocBlock,
  69.         Ofs_StartWriteBack,
  70.  
  71. };
  72. static     Fscache_Backend *cacheBackendPtr = (Fscache_Backend *) NIL;
  73.  
  74.  
  75.  
  76. /*
  77.  *----------------------------------------------------------------------
  78.  *
  79.  * Ofs_Init --
  80.  *
  81.  *    Initialized code of the OFS disk storage manager module.
  82.  *
  83.  * Results:
  84.  *
  85.  * Side effects:
  86.  *    Registers OFS with Fsdm module.
  87.  *
  88.  *----------------------------------------------------------------------
  89.  */
  90. void
  91. Ofs_Init()
  92. {
  93.     Fsdm_RegisterDiskManager("OFS", Ofs_AttachDisk);
  94. }
  95.  
  96. /*
  97.  *----------------------------------------------------------------------
  98.  *
  99.  * Ofs_AttachDisk --
  100.  *
  101.  *    Try to attach a OFS disk from the specified disk.
  102.  *
  103.  * Results:
  104.  *
  105.  * Side effects:
  106.  *
  107.  *----------------------------------------------------------------------
  108.  */
  109. ReturnStatus
  110. Ofs_AttachDisk(devicePtr, localName, flags, domainNumPtr)
  111.     Fs_Device    *devicePtr;    /* Device containing file system. */
  112.     char *localName;        /* The local prefix for the domain */
  113.     int  flags;            /* Attach flags. */
  114.     int *domainNumPtr;        /* OUT: Domain number allocated. */
  115.  
  116. {
  117.     ReturnStatus status;        /* Error code */
  118.     register Address buffer;        /* Read buffer */
  119.     int headerSector;            /* Starting sector of domain header */
  120.     int numHeaderSectors;        /* Number of sectors in domain header */
  121.     int summarySector;            /* Sector of summary information. */
  122.     Ofs_SummaryInfo *summaryInfoPtr;    /* Pointer to summary info. */
  123.     Fs_IOParam    io;            /* I/O Parameter block */
  124.     Fs_IOReply    reply;            /* Results of I/O */
  125.     int        partition;
  126.     Fsdm_Domain    *domainPtr;    
  127.     Ofs_Domain    *ofsPtr;
  128.  
  129.  
  130.     headerSector = summarySector = 0;
  131.  
  132.     bzero((Address)&io, sizeof(io));
  133.     bzero((Address)&reply, sizeof(reply));
  134.     /*
  135.      * Read the zero'th sector of the partition.  It has a copy of the
  136.      * zero'th sector of the whole disk which describes how the rest of the
  137.      * domain's zero'th cylinder is layed out.
  138.      */
  139.     buffer = (Address)malloc(DEV_BYTES_PER_SECTOR * OFS_NUM_DOMAIN_SECTORS);
  140.     io.buffer = buffer;
  141.     io.length = DEV_BYTES_PER_SECTOR;
  142.     io.offset = 0;
  143.     status = (*devFsOpTable[DEV_TYPE_INDEX(devicePtr->type)].read)(devicePtr,
  144.         &io, &reply);
  145.     if (status != SUCCESS) {
  146.     free(buffer);
  147.     return(status);
  148.     }
  149.     /*
  150.      * Check for different disk formats, and figure out how the rest
  151.      * of the zero'th cylinder is layed out.
  152.      */
  153.     if (Fsdm_IsSunLabel(buffer)) {
  154.     Ofs_DomainHeader    *domainHeaderPtr = (Ofs_DomainHeader *) buffer;
  155.     int            i;
  156.     /*
  157.      * For Sun formatted disks we put the domain header well past
  158.      * the disk label and the boot program.
  159.      */
  160.     numHeaderSectors = OFS_NUM_DOMAIN_SECTORS;
  161.     io.length = DEV_BYTES_PER_SECTOR * OFS_NUM_DOMAIN_SECTORS;
  162.     for (i = 2; i < FSDM_MAX_BOOT_SECTORS + 3; i+= FSDM_BOOT_SECTOR_INC) {
  163.         io.offset = i * DEV_BYTES_PER_SECTOR;
  164.         io.length = DEV_BYTES_PER_SECTOR * OFS_NUM_DOMAIN_SECTORS;
  165.         status = (*devFsOpTable[DEV_TYPE_INDEX(devicePtr->type)].read)
  166.             (devicePtr, &io, &reply);
  167.         if (status != SUCCESS) {
  168.         free(buffer);
  169.         return(status);
  170.         }
  171.         if (domainHeaderPtr->magic == OFS_DOMAIN_MAGIC) {
  172.         headerSector = i;
  173.         summarySector = i - 1;
  174.             break;
  175.         }
  176.     }
  177.     if (i >= FSDM_MAX_BOOT_SECTORS + 3) {
  178.         free(buffer);
  179.         return(FAILURE);
  180.     }
  181.     } else if (Fsdm_IsSpriteLabel(buffer)) {
  182.     register Fsdm_DiskHeader *diskHeaderPtr;
  183.     diskHeaderPtr = (Fsdm_DiskHeader *)buffer;
  184.     headerSector = diskHeaderPtr->domainSector;
  185.     numHeaderSectors = diskHeaderPtr->numDomainSectors;
  186.     summarySector = diskHeaderPtr->summarySector;
  187.     } else {
  188.     io.buffer = buffer;
  189.     io.length = DEV_BYTES_PER_SECTOR;
  190.     io.offset = DEC_LABEL_SECTOR * DEV_BYTES_PER_SECTOR;
  191.     status = (*devFsOpTable[DEV_TYPE_INDEX(devicePtr->type)].read)
  192.         (devicePtr, &io, &reply);
  193.     if (status != SUCCESS) {
  194.         free(buffer);
  195.         return(status);
  196.     }
  197.     if (Fsdm_IsDecLabel(buffer)){
  198.         register Dec_DiskLabel *decLabelPtr;
  199.         decLabelPtr = (Dec_DiskLabel *)buffer;
  200.         headerSector = decLabelPtr->domainSector;
  201.         numHeaderSectors = decLabelPtr->numDomainSectors;
  202.         summarySector = decLabelPtr->summarySector;
  203.         if (summarySector < 0) {
  204.         free(buffer);
  205.         return(FAILURE);
  206.         }
  207.     } else {
  208.         free(buffer);
  209.         return(FAILURE);
  210.     }
  211.     }
  212.     /*
  213.      * Read in summary information.
  214.      */
  215.     io.length = DEV_BYTES_PER_SECTOR;
  216.     io.offset = summarySector * DEV_BYTES_PER_SECTOR;
  217.     status = (*devFsOpTable[DEV_TYPE_INDEX(devicePtr->type)].read)
  218.         (devicePtr, &io, &reply); 
  219.     if (status != SUCCESS) {
  220.     free(buffer);
  221.     return(status);
  222.     }
  223.     summaryInfoPtr = (Ofs_SummaryInfo *) buffer;
  224.  
  225.     /*
  226.      * Read the domain header and save it with the domain state.
  227.      */
  228.     buffer = (Address)malloc(DEV_BYTES_PER_SECTOR * numHeaderSectors);
  229.     io.buffer = buffer;
  230.     io.length = numHeaderSectors * DEV_BYTES_PER_SECTOR;
  231.     io.offset = headerSector * DEV_BYTES_PER_SECTOR;
  232.     status = (*devFsOpTable[DEV_TYPE_INDEX(devicePtr->type)].read)(devicePtr,
  233.         &io, &reply);
  234.     if (status != SUCCESS) {
  235.     free((char *) summaryInfoPtr);
  236.     free(buffer);
  237.     return(status);
  238.     } else if (((Ofs_DomainHeader *)buffer)->magic != OFS_DOMAIN_MAGIC) {
  239.     free((char *) summaryInfoPtr);
  240.     free(buffer);
  241.     return(FAILURE);
  242.     }
  243.     /*
  244.      * Make the domain flag positive to inform caller that this is an
  245.      * OFS file system even if the mount fails.
  246.      */
  247.     *domainNumPtr = 1;
  248.     /* 
  249.      * Verify the device specification by checking the partition
  250.      * number kept in the domain header. 
  251.      */
  252.     partition = ((Ofs_DomainHeader *)buffer)->device.unit;
  253.     if (partition >= 0 && partition < FSDM_NUM_DISK_PARTS) {
  254.     if ((devicePtr->unit % FSDM_NUM_DISK_PARTS) != partition) {
  255.         /*
  256.          * File system was built on a different partition.
  257.          */
  258.         free((char *) summaryInfoPtr);
  259.         free(buffer);
  260.         return(FAILURE);
  261.     }
  262.     }
  263.     status = Fsdm_InstallDomain(summaryInfoPtr->domainNumber,
  264.         ((Ofs_DomainHeader *)buffer)->device.serverID, 
  265.         localName, flags, &domainPtr);
  266.     if (status != SUCCESS) {
  267.     if (status == FS_FILE_BUSY) {
  268.         if (domainPtr->flags & FSDM_DOMAIN_ATTACH_BOOT) {
  269.         domainPtr->flags &= ~FSDM_DOMAIN_ATTACH_BOOT;
  270.         summaryInfoPtr->flags &=  ~OFS_DOMAIN_JUST_CHECKED;
  271.         printf("Ofs_AttachDisk: clearing just-checked bit\n");
  272.         if ((flags & FS_ATTACH_READ_ONLY) == 0) {
  273.             io.buffer = (char *) summaryInfoPtr;
  274.             io.length = DEV_BYTES_PER_SECTOR;
  275.             io.offset = summarySector * DEV_BYTES_PER_SECTOR;
  276.             status = 
  277.              (*devFsOpTable[DEV_TYPE_INDEX(devicePtr->type)].write)
  278.                     (devicePtr, &io, &reply);
  279.             if (status != SUCCESS) {
  280.             panic( 
  281.         "Ofs_AttachDisk: Summary write failed, status %x\n", status);
  282.             }
  283.         }
  284.         }
  285.         status = FS_DOMAIN_UNAVAILABLE;
  286.     }
  287.     free((char *) summaryInfoPtr);
  288.     free(buffer);
  289.     return status;
  290.     }
  291.     if (cacheBackendPtr == (Fscache_Backend *) NIL) {
  292.     cacheBackendPtr = 
  293.         Fscache_RegisterBackend(&ofsBackendRoutines,(ClientData) 0, 0);
  294.     }
  295.  
  296.     ofsPtr = (Ofs_Domain *) malloc(sizeof(Ofs_Domain));
  297.     bzero((char *) ofsPtr, sizeof(Ofs_Domain));
  298.  
  299.     domainPtr->backendPtr = cacheBackendPtr;
  300.     domainPtr->domainOpsPtr = &ofsDomainOps;
  301.     domainPtr->clientData = (ClientData) ofsPtr;
  302.  
  303.     ofsPtr->domainPtr = domainPtr;
  304.     ofsPtr->headerPtr = (Ofs_DomainHeader *) buffer;
  305.     ofsPtr->summaryInfoPtr = summaryInfoPtr;
  306.     ofsPtr->summarySector = summarySector;
  307.     ofsPtr->blockDevHandlePtr = (DevBlockDeviceHandle *) (devicePtr->data);
  308.     /*
  309.      * Fix up the device information in the domain header
  310.      * as this is used by the block I/O routines.
  311.      */
  312.     ofsPtr->headerPtr->device.unit = devicePtr->unit;
  313.     ofsPtr->headerPtr->device.type = devicePtr->type;
  314.     ofsPtr->headerPtr->device.data = devicePtr->data;
  315.  
  316.     /*
  317.      * After reading the low level header information from the disk we
  318.      * install the domain into the set of active domains and initialize
  319.      * things for block I/O.
  320.      */
  321.  
  322.     status = OfsIOInit(domainPtr);
  323.     if (status != SUCCESS) {
  324.     printf( "Ofs_InitializeDomain: can't initialize block I/O %x\n",
  325.         status);
  326.     domainPtr->flags |= FSDM_DOMAIN_DOWN;
  327.     return(status);
  328.     }
  329.     /*
  330.      * Set the domainNumber in the summary info so next time we will be
  331.      * mounted under the same domain number.
  332.      */
  333.     summaryInfoPtr->domainNumber = domainPtr->domainNumber;
  334.     *domainNumPtr = domainPtr->domainNumber;
  335.  
  336.     /*
  337.      * Finally mark the domain to indicate that if we go down hard,
  338.      * clean recovery of this domain is impossible.
  339.      */
  340.     if ((summaryInfoPtr->flags & OFS_DOMAIN_NOT_SAFE) == 0) {
  341.     summaryInfoPtr->flags |= OFS_DOMAIN_ATTACHED_CLEAN;
  342.     } else {
  343.     summaryInfoPtr->flags &= ~OFS_DOMAIN_ATTACHED_CLEAN;
  344.     }
  345.     summaryInfoPtr->flags |= OFS_DOMAIN_NOT_SAFE |
  346.                     OFS_DOMAIN_TIMES_VALID;
  347.     if (!(flags & FS_DEFAULT_DOMAIN)) {
  348.     summaryInfoPtr->flags &= ~OFS_DOMAIN_JUST_CHECKED;
  349.     }
  350.     summaryInfoPtr->attachSeconds = Fsutil_TimeInSeconds();
  351.     if ((flags & FS_ATTACH_READ_ONLY) == 0) {
  352.     status = OfsWriteBackSummaryInfo(ofsPtr);
  353.     if (status != SUCCESS) {
  354.         panic( "Ofs_AttachDisk: Summary write failed, status %x\n", status);
  355.     }
  356.     } 
  357.     return status;
  358.  
  359. }
  360.  
  361. /*
  362.  *----------------------------------------------------------------------
  363.  *
  364.  * OfsIOInit --
  365.  *
  366.  *    Initialize a particular local domain for I/O.
  367.  *
  368.  * Results:
  369.  *    Error code returned from initializing data block and file
  370.  *    descriptor allocation.
  371.  *
  372.  * Side effects:
  373.  *    Physical file handle for the domain is initialized.
  374.  *
  375.  *----------------------------------------------------------------------
  376.  */
  377.  
  378. ReturnStatus
  379. OfsIOInit(domainPtr)
  380.     Fsdm_Domain    *domainPtr;
  381. {
  382.     register    Ofs_Domain    *ofsPtr;
  383.     ReturnStatus        status;
  384.     Fscache_Attributes        attr;
  385.     int            domainNumber;
  386.  
  387.     ofsPtr = OFS_PTR_FROM_DOMAIN(domainPtr);
  388.     domainNumber = domainPtr->domainNumber;
  389.     /*
  390.      * Initialize the file handle used for raw I/O, i.e. for file descriptors,
  391.      * the bitmaps, and indirect blocks.
  392.      */
  393.  
  394.     bzero((Address)&ofsPtr->physHandle, sizeof(ofsPtr->physHandle));
  395.     ofsPtr->physHandle.hdr.fileID.major = domainNumber;
  396.     ofsPtr->physHandle.hdr.fileID.minor = 0;
  397.     ofsPtr->physHandle.hdr.fileID.type = FSIO_LCL_FILE_STREAM;
  398.     ofsPtr->physHandle.descPtr = (Fsdm_FileDescriptor *)NIL;
  399.  
  400.     bzero((Address)&attr, sizeof(attr));
  401.     attr.lastByte = 0x7fffffff;
  402.     Fscache_FileInfoInit(&ofsPtr->physHandle.cacheInfo,
  403.             (Fs_HandleHeader *) &ofsPtr->physHandle,
  404.             0, TRUE, &attr, domainPtr->backendPtr);
  405.  
  406.     status = OfsBlockAllocInit(ofsPtr);
  407.     if (status != SUCCESS) {
  408.     printf( "Block Alloc init failed for domain %d\n",
  409.         domainNumber);
  410.     return(status);
  411.     }
  412.     status = OfsFileDescAllocInit(ofsPtr);
  413.     if (status != SUCCESS) {
  414.     printf( "File Desc alloc init failed for domain %d\n",
  415.         domainNumber);
  416.     return(status);
  417.     }
  418.     return(status);
  419. }
  420.  
  421.  
  422.  
  423. /*
  424.  *----------------------------------------------------------------------
  425.  *
  426.  * Ofs_DetachDisk --
  427.  *
  428.  *    Remove a local domain from the set of accessible domains.
  429.  *
  430.  * Results:
  431.  *    SUCCESS if the domain was already attached and all the outstanding
  432.  *    file handles could be recalled.
  433.  *
  434.  * Side effects:
  435.  *    Clears the prefix table entry for the domain.
  436.  *
  437.  *----------------------------------------------------------------------
  438.  */
  439. ReturnStatus
  440. Ofs_DetachDisk(domainPtr)
  441.     Fsdm_Domain    *domainPtr;
  442. {
  443.     register Ofs_Domain    *ofsPtr = OFS_PTR_FROM_DOMAIN(domainPtr);
  444.     Ofs_DomainHeader    *headerPtr;
  445.     int            i;
  446.     ReturnStatus    status;
  447.     int            blocksLeft, blocksSkipped;
  448.  
  449.     /*
  450.      * Write all dirty blocks, bitmaps, etc. to disk and take the
  451.      * domain down.
  452.      */
  453.     Fscache_WriteBack(-1, &blocksLeft, FALSE);    /* Write back the cache. */
  454.     headerPtr = ofsPtr->headerPtr;
  455.     Fscache_FileWriteBack(&ofsPtr->physHandle.cacheInfo,
  456.         headerPtr->fileDescOffset,
  457.         headerPtr->fileDescOffset + 
  458.         (headerPtr->numFileDesc / FSDM_FILE_DESC_PER_BLOCK) + 1,
  459.         FSCACHE_WRITE_BACK_AND_INVALIDATE, &blocksSkipped);
  460.     Fsdm_DomainWriteBack(ofsPtr->physHandle.hdr.fileID.major, FALSE, TRUE);
  461.     /* Write back domain info. */
  462.     /*
  463.      * We successfully brought down the disk, so mark it as OK.
  464.      * The detach time is noted in order to track how long disks are available.
  465.      */
  466.     ofsPtr->summaryInfoPtr->flags &= ~OFS_DOMAIN_NOT_SAFE;
  467.     ofsPtr->summaryInfoPtr->flags &= ~OFS_DOMAIN_JUST_CHECKED;
  468.     ofsPtr->summaryInfoPtr->detachSeconds = Fsutil_TimeInSeconds();
  469.     status = OfsWriteBackSummaryInfo(ofsPtr);
  470.     if (status != SUCCESS) {
  471.     panic( "Ofs_DetachDisk: Summary write failed, status %x\n",
  472.             status);
  473.     }
  474.  
  475.     /*
  476.      * Free up resources for the domain.
  477.      */
  478.     Sync_LockClear(&ofsPtr->dataBlockLock);
  479.     Sync_LockClear(&ofsPtr->fileDescLock);
  480.     free((Address)ofsPtr->headerPtr);
  481.     free((Address)ofsPtr->summaryInfoPtr);
  482.     free((Address)ofsPtr->dataBlockBitmap);
  483.     free((Address)ofsPtr->cylinders);
  484.     for (i = 0; i < OFS_NUM_FRAG_SIZES; i++) {
  485.     List_Links    *fragList;
  486.     OfsFragment    *fragPtr;
  487.     fragList = ofsPtr->fragLists[i];
  488.     while (!List_IsEmpty(fragList)) {
  489.         fragPtr = (OfsFragment *)List_First(fragList);
  490.         List_Remove((List_Links *)fragPtr);
  491.         free((Address)fragPtr);
  492.     }
  493.     free((Address)fragList);
  494.     }
  495.     free((Address)ofsPtr->fileDescBitmap);
  496.  
  497.     return(SUCCESS);
  498. }
  499.  
  500.  
  501. /*
  502.  *----------------------------------------------------------------------
  503.  *
  504.  * Ofs_DomainWriteBack --
  505.  *
  506.  *    Force all domain information to disk.
  507.  *
  508.  * Results:
  509.  *    Error code if the write failed.
  510.  *
  511.  * Side effects:
  512.  *    None.
  513.  *
  514.  *----------------------------------------------------------------------
  515.  */
  516. ReturnStatus
  517. Ofs_DomainWriteBack(domainPtr, shutdown)
  518.     Fsdm_Domain    *domainPtr;    /* Domain to writeback. */
  519.     Boolean    shutdown;    /* TRUE if are syncing to shutdown the system.*/
  520. {
  521.     register    Ofs_Domain    *ofsPtr = OFS_PTR_FROM_DOMAIN(domainPtr);
  522.     ReturnStatus        status1, status2;
  523.  
  524.     status1 = OfsWriteBackDataBlockBitmap(ofsPtr);
  525.     status2 = OfsWriteBackFileDescBitmap(ofsPtr);
  526.     if (shutdown && status1 == SUCCESS && status2 == SUCCESS) {
  527.     ofsPtr->summaryInfoPtr->flags &= ~OFS_DOMAIN_NOT_SAFE;
  528.     ofsPtr->summaryInfoPtr->detachSeconds = Fsutil_TimeInSeconds();
  529.     } else {
  530.     ofsPtr->summaryInfoPtr->flags |= OFS_DOMAIN_NOT_SAFE;
  531.     }
  532.     (void)OfsWriteBackSummaryInfo(ofsPtr);
  533.     return (status1 == SUCCESS) ? status2 : status1;
  534. }
  535.  
  536.  
  537. /*
  538.  *----------------------------------------------------------------------
  539.  * The following routines are used by device drivers to map from block
  540.  * and sector numbers to disk addresses.  There are two sets, one for
  541.  * drivers that use logical sector numbers (i.e. SCSI) and the other
  542.  * for <cyl,head,sector> format disk addresses.
  543.  *----------------------------------------------------------------------
  544.  */
  545.  
  546. /*
  547.  *----------------------------------------------------------------------
  548.  *
  549.  * OfsBlocksToSectors --
  550.  *
  551.  *    Convert from block indexes (actually, fragment indexes) to
  552.  *    sectors using the geometry information on the disk.  This
  553.  *    is a utility for block device drivers.
  554.  *
  555.  * Results:
  556.  *    The sector number that corresponds to the fragment index.
  557.  *    The caller has to make sure that its I/O doesn't cross a
  558.  *    filesystem block boundary.
  559.  *
  560.  * Side effects:
  561.  *    None.
  562.  *
  563.  *----------------------------------------------------------------------
  564.  */
  565. #define SECTORS_PER_FRAG    (FS_FRAGMENT_SIZE / DEV_BYTES_PER_SECTOR)
  566. int
  567. OfsBlocksToSectors(fragNumber, geoPtr)
  568.     int fragNumber;    /* Fragment index to map into block index */
  569.     register Ofs_Geometry *geoPtr;    /* ClientData from the device info */
  570. {
  571.     register int sectorNumber;    /* The sector corresponding to the fragment */
  572.     register int cylinder;    /* The cylinder number of the fragment */
  573.     register int rotationalSet;    /* The rotational set with cylinder of frag */
  574.     register int blockNumber;    /* The block number within rotational set */
  575.  
  576.     blockNumber        = fragNumber / FS_FRAGMENTS_PER_BLOCK;
  577.     cylinder        = blockNumber / geoPtr->blocksPerCylinder;
  578.     /*
  579.      * This is the old way of doing things.  We have to deal with rotational
  580.      * sets and the like.
  581.      */
  582.     if (geoPtr->rotSetsPerCyl > 0) {    
  583.     
  584.     blockNumber        -= cylinder * geoPtr->blocksPerCylinder;
  585.     rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  586.     blockNumber        -= rotationalSet * geoPtr->blocksPerRotSet;
  587.     
  588.     sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
  589.               geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
  590.               rotationalSet +
  591.               geoPtr->blockOffset[blockNumber];
  592.     sectorNumber += (fragNumber % FS_FRAGMENTS_PER_BLOCK) * 
  593.             SECTORS_PER_FRAG;
  594.     } else if (geoPtr->rotSetsPerCyl == OFS_SCSI_MAPPING) {
  595.     /*
  596.      * The new way is to map blocks from the start of the disk without
  597.      * regard for rotational sets.  There is essentially one rotational
  598.      * set per disk.
  599.      */
  600.     sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
  601.             fragNumber * SECTORS_PER_FRAG - cylinder * 
  602.             geoPtr->blocksPerCylinder * FS_FRAGMENTS_PER_BLOCK *
  603.             SECTORS_PER_FRAG;
  604.     } else {
  605.     panic("Unknown mapping in domain geometry information\n");
  606.     sectorNumber = -1;
  607.     }
  608.     return(sectorNumber);
  609. }
  610.  
  611. /*
  612.  *----------------------------------------------------------------------
  613.  *
  614.  * Ofs_BlocksToDiskAddr --
  615.  *
  616.  *    Convert from block indexes (actually, fragment indexes) to
  617.  *    disk address (head, cylinder, sector) using the geometry information
  618.  *     on the disk.  This is a utility for block device drivers.
  619.  *
  620.  * Results:
  621.  *    The disk address that corresponds to the disk address.
  622.  *    The caller has to make sure that its I/O doesn't cross a
  623.  *    filesystem block boundary.
  624.  *
  625.  * Side effects:
  626.  *    None.
  627.  *
  628.  *----------------------------------------------------------------------
  629.  */
  630. void
  631. Ofs_BlocksToDiskAddr(fragNumber, data, diskAddrPtr)
  632.     int fragNumber;    /* Fragment index to map into block index */
  633.     ClientData data;    /* ClientData from the device info */
  634.     Dev_DiskAddr *diskAddrPtr;
  635. {
  636.     register Ofs_Geometry *geoPtr;
  637.     register int sectorNumber;    /* The sector corresponding to the fragment */
  638.     register int cylinder;    /* The cylinder number of the fragment */
  639.     register int rotationalSet;    /* The rotational set with cylinder of frag */
  640.     register int blockNumber;    /* The block number within rotational set */
  641.  
  642.     geoPtr         = (Ofs_Geometry *)data;
  643.     /*
  644.      * Map to block number because the rotational sets are laid out
  645.      * relative to blocks.  After that the cylinder is easy because we know
  646.      * blocksPerCylinder.  To get the head and sector we first get the
  647.      * rotational set (described in fsDisk.h) of the block and the
  648.      * block's sector offset (relative to the rotational set!).  This complex
  649.      * algorithm crops up because there isn't necessarily an even number
  650.      * of blocks per track.  The 'blockOffset' array in the geometry gives
  651.      * a sector index of each successive block in a rotational set. Finally,
  652.      * we can use the sectorsPerTrack to get the head and sector.
  653.      */
  654.     blockNumber        = fragNumber / FS_FRAGMENTS_PER_BLOCK;
  655.     cylinder        = blockNumber / geoPtr->blocksPerCylinder;
  656.     blockNumber        -= cylinder * geoPtr->blocksPerCylinder;
  657.     diskAddrPtr->cylinder = cylinder;
  658.  
  659.     rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  660.     blockNumber        -= rotationalSet * geoPtr->blocksPerRotSet;
  661. /*
  662.  * The follow statment had to be broken into two because the compiler used
  663.  * register d2 to do the modulo operation, but wasn't saving its value.
  664.  */
  665.     sectorNumber    = geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
  666.               rotationalSet + geoPtr->blockOffset[blockNumber];
  667.     sectorNumber    +=
  668.             (fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
  669.  
  670.     diskAddrPtr->head    = sectorNumber / geoPtr->sectorsPerTrack;
  671.     diskAddrPtr->sector = sectorNumber -
  672.               diskAddrPtr->head * geoPtr->sectorsPerTrack;
  673. }
  674.  
  675. /*
  676.  *----------------------------------------------------------------------
  677.  *
  678.  * Ofs_SectorsToRawDiskAddr --
  679.  *
  680.  *      Convert from a sector offset to a raw disk address (cyl, head,
  681.  *      sector) using the geometry information on the disk.  This is a
  682.  *      utility for raw device drivers and does not pay attention to the
  683.  *      rotational position of filesystem disk blocks.
  684.  *
  685.  *    This should be moved to Dev
  686.  *
  687.  * Results:
  688.  *    The disk address that corresponds exactly to the byte offset.
  689.  *
  690.  * Side effects:
  691.  *    None.
  692.  *
  693.  *----------------------------------------------------------------------
  694.  */
  695. int
  696. Ofs_SectorsToRawDiskAddr(sector, numSectors, numHeads, diskAddrPtr)
  697.     int sector;        /* Sector number (counting from zero 'til the total
  698.              * number of sectors in the disk) */
  699.     int numSectors;    /* Number of sectors per track */
  700.     int numHeads;    /* Number of heads on the disk */
  701.     Dev_DiskAddr *diskAddrPtr;
  702. {
  703.     register int sectorsPerCyl;    /* The rotational set with cylinder of frag */
  704.  
  705.     sectorsPerCyl        = numSectors * numHeads;
  706.     diskAddrPtr->cylinder    = sector / sectorsPerCyl;
  707.     sector            -= diskAddrPtr->cylinder * sectorsPerCyl;
  708.     diskAddrPtr->head        = sector / numSectors;
  709.     diskAddrPtr->sector        = sector - numSectors * diskAddrPtr->head;
  710.     return 0;
  711. }
  712.  
  713.  
  714. /*
  715.  *----------------------------------------------------------------------
  716.  *
  717.  * Ofs_RereadSummaryInfo --
  718.  *
  719.  *    Reread the summary sector associated with the prefix and update
  720.  *    the domain information. This should be called if the summary
  721.  *    sector on the disk has been changed since the domain was attached.
  722.  *
  723.  * Results:
  724.  *    SUCCESS if the summary sector was read correctly and the 
  725.  *    information was updated
  726.  *
  727.  * Side effects:
  728.  *    The summary sector information associated with the domain is
  729.  *    updated.
  730.  *
  731.  *----------------------------------------------------------------------
  732.  */
  733.  
  734. ReturnStatus
  735. Ofs_RereadSummaryInfo(domainPtr)
  736.     Fsdm_Domain        *domainPtr;    /* Domain to reread summary for. */
  737. {
  738.     register Ofs_Domain    *ofsPtr = OFS_PTR_FROM_DOMAIN(domainPtr);
  739.     ReturnStatus    status;
  740.     Fs_Device        *devicePtr;
  741.     Fs_IOParam        io;
  742.     Fs_IOReply        reply;
  743.     char        buffer[DEV_BYTES_PER_SECTOR];
  744.  
  745.     bzero((Address)&io, sizeof(io));
  746.     bzero((Address)&reply, sizeof(reply));
  747.     devicePtr = &(ofsPtr->headerPtr->device);
  748.     io.buffer = buffer;
  749.     io.length = DEV_BYTES_PER_SECTOR;
  750.     io.offset = ofsPtr->summarySector * DEV_BYTES_PER_SECTOR;
  751.     status = (*devFsOpTable[DEV_TYPE_INDEX(devicePtr->type)].read)
  752.         (devicePtr, &io, &reply); 
  753.     /*
  754.      * Copy information from the buffer.
  755.      */
  756.     if (status == SUCCESS) { 
  757.     bcopy(buffer, (char *)ofsPtr->summaryInfoPtr, reply.length);
  758.     }
  759.     return status;
  760. }
  761.  
  762.  
  763. /*
  764.  *----------------------------------------------------------------------
  765.  *
  766.  * Ofs_DirOpStart --
  767.  *
  768.  *    Mark the start of a directory operation on an OFS file system.
  769.  *    Since OFS uses fscheck to do crash recovery, this is a noop.
  770.  *
  771.  * Results:
  772.  *    NIL
  773.  *    
  774.  *
  775.  * Side effects:
  776.  *    None.
  777.  *
  778.  *----------------------------------------------------------------------
  779.  */
  780.  
  781. ClientData
  782. Ofs_DirOpStart(domainPtr, opFlags, name, nameLen, fileNumber, fileDescPtr,
  783.          dirFileNumber, dirOffset, dirFileDescPtr)
  784.     Fsdm_Domain    *domainPtr;    /* Domain containing the object being modified.
  785.                  */
  786.     int        opFlags;    /* Operation code and flags. See fsdm.h for
  787.                  * definitions. */
  788.     char    *name;        /* Name of object being operated on. */
  789.     int        nameLen;    /* Length in characters of name. */
  790.     int        fileNumber;    /* File number of objecting being operated on.*/
  791.     Fsdm_FileDescriptor *fileDescPtr; /* FileDescriptor object being operated on
  792.                        * before operation starts. */
  793.     int        dirFileNumber;    /* File number of directory containing object.*/
  794.     int        dirOffset;    /* Byte offset into directory of the directory
  795.                  * entry containing operation. */
  796.     Fsdm_FileDescriptor *dirFileDescPtr; /* FileDescriptor of directory before
  797.                       * operation starts. */
  798. {
  799.     return (ClientData) -1;
  800. }
  801.  
  802. /*
  803.  *----------------------------------------------------------------------
  804.  *
  805.  * Ofs_DirOpEnd --
  806.  *
  807.  *    Mark the end of a directory operation on an OFS file system.
  808.  *    Since OFS uses fscheck to do crash recovery, this is a noop.
  809.  *
  810.  * Results:
  811.  *    None
  812.  *    
  813.  *
  814.  * Side effects:
  815.  *    None.
  816.  *
  817.  *----------------------------------------------------------------------
  818.  */
  819.  
  820. void
  821. Ofs_DirOpEnd(domainPtr, clientData, status, opFlags, name, nameLen, 
  822.         fileNumber,  fileDescPtr, dirFileNumber, dirOffset, 
  823.         dirFileDescPtr)
  824.     Fsdm_Domain    *domainPtr;    /* Domain containing the object modified. */
  825.     ClientData    clientData;    /* ClientData as returned by DirOpStart. */
  826.     ReturnStatus status;    /* Return status of the operation, SUCCESS if
  827.                  * operation succeeded. FAILURE otherwise. */
  828.     int        opFlags;    /* Operation code and flags. See fsdm.h for
  829.                  * definitions. */
  830.     char    *name;        /* Name of object being operated on. */
  831.     int        nameLen;    /* Length in characters of name. */
  832.     int        fileNumber;    /* File number of objecting being operated on.*/
  833.     Fsdm_FileDescriptor *fileDescPtr; /* FileDescriptor object after
  834.                       * operation.*/
  835.     int        dirFileNumber;    /* File number of directory containing object.*/
  836.     int        dirOffset;    /* Byte offset into directory of the directory
  837.                  * entry containing operation. */
  838.     Fsdm_FileDescriptor *dirFileDescPtr; /* FileDescriptor of directory after
  839.                       * operation. */
  840. {
  841.     return;
  842. }
  843.  
  844.